﻿using System;
using System.Linq;
using System.Web.Mvc;
using AdAggregator.Monitoring;
using ClothingAggregator.Models;
using ClothingAggregator.Models.Monitoring;
using ClothingAggregator.Utils;

namespace ClothingAggregator.Controllers
{
    public class MonitoringController : Controller
    {
        private MonitoringContext ctx = new MonitoringContext();

        [HttpGet]
        public ActionResult Index()
        {
            ViewBag.Tasks = ctx.MonitoringTasks.OrderByDescending(t => t.CreatedAt).ToList();
            return View();
        }

        [HttpPost]
        public ActionResult Monitor(string url)
        {
            if (string.IsNullOrEmpty(url)) return Json(new { result = "FAIL" });
            var aggregator = Session["aggregator"] as MyAggregator ?? new MyAggregator();
            var ad = aggregator.Results.FirstOrDefault(a => a.Link == url);
            var uniqueId = EncryptionUtils.EncryptString(url);
            var task = new MonitoringTask
            {
                Active = true,
                Frequency = 1,
                Id = uniqueId
            };

            if (ctx.AddNewMonitoringTask(task))
            {
                PriceMonitoring<MyAdvertisement>.StartMonitoringTask(task, ad, ctx.AddNewMonitoringResult);

                var firstMonitoringResult = new MonitoringResult<MyAdvertisement>
                    {
                        LastUpdate = DateTime.Now,
                        PricedAdvertisement = ad,
                        MonitoringTaskId = uniqueId
                    };

                ctx.AddNewMonitoringResult(firstMonitoringResult);
                return Json(new { result = "OK" });
            }
            return Json(new { result = "DUPLICATE" });
        }

        [HttpPost]
        public ActionResult StartMonitoring(string taskId)
        {
            if (string.IsNullOrEmpty(taskId)) return Json(new { result = "FAIL" });

            var dbTask = ChangeTaskActivity(true, taskId);
            if (dbTask == null) return Json(new { result = "FAIL" });
            var task = dbTask.ToMonitoringTask();

            if (dbTask.History.Count == 0) return Json(new { result = "FAIL" });
            var lastResult = dbTask.History.Aggregate((max, nextValue) => (nextValue.LastUpdate > max.LastUpdate ? nextValue : max));
            var aggregator = Session["aggregator"] as MyAggregator ?? new MyAggregator();
            lastResult.Advertisement.Source = aggregator.GetWebsites().FirstOrDefault(w => w.GetType().Name == lastResult.Advertisement.SourceString);
            PriceMonitoring<MyAdvertisement>.StartMonitoringTask(task, lastResult.Advertisement, ctx.AddNewMonitoringResult);
            return Json(new { result = "ACTIVE" });
        }

        [HttpPost]
        public ActionResult StopMonitoring(string taskId)
        {
            if (string.IsNullOrEmpty(taskId)) return Json(new { result = "FAIL" });
            var dbTask = ChangeTaskActivity(false, taskId);
            if (dbTask == null) return Json(new { result = "FAIL" });
            var task = dbTask.ToMonitoringTask();
            PriceMonitoring<MyAdvertisement>.StopMonitoringTask(task);
            return Json(new { result = "STOPPED" });
        }

        [HttpPost]
        public ActionResult RemoveTask(string taskId)
        {
            if (string.IsNullOrEmpty(taskId)) return Json(new { result = "FAIL" });
            var task = ctx.MonitoringTasks.FirstOrDefault(t => t.Id == taskId);
            if (task == null) return Json(new { result = "FAIL" });
            PriceMonitoring<MyAdvertisement>.StopMonitoringTask(task.ToMonitoringTask());
            ctx.MonitoringTasks.Remove(task);
            ctx.SaveChanges();
            return Json(new { result = "OK" });
        }

        private MyMonitoringTask ChangeTaskActivity(bool toActive, string taskId)
        {
            var dbTask = ctx.MonitoringTasks.FirstOrDefault(t => t.Id == taskId);
            if (dbTask != null)
            {
                dbTask.Active = toActive;
                ctx.SaveChanges();
            }
            return dbTask;
        }
    }
}
